//
// Created by wuzhuya on 23-3-27.
//

#include "udp.h"

void udp_server(int port) {
    pthread_t udpSocketServerRecv;
    int sockSrv = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sockSrv <= 0) {
        printf("socket err!\n");
        exit(-1);
    }
    struct sockaddr_in addr;
    uint32_t addr_size = sizeof(struct sockaddr);
    addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    addr.sin_port = htons(port);
    addr.sin_family = AF_INET;
    int i1 = bind(sockSrv, (struct sockaddr *) &addr, addr_size);
    if (i1 < 0) {
        printf("bind error\n");
        return;
    }
    // 开启新线程接收消息
    pthread_create(&udpSocketServerRecv, NULL, udp_server_recv, (void *) &sockSrv);
    printf("\n");
    // 主线程发送消息
    char host[1024];
    char message[1024];
    int serverPort;
    while (1) {
        memset(host, 0, 1024);
        memset(message, 0, 1024);
        memset(&serverPort, 0, 4);
        printf("input address: ");
        scanf("%s", host);
        printf("input port: ");
        scanf("%d", &serverPort);
        printf("input message: ");
        scanf("%s", message);
        udp_client(host, serverPort, message);
    }
}

void *udp_server_recv(void *socket) {
    char buf[1024];
    struct sockaddr_in cli_addr;
    size_t cli_len = sizeof(cli_addr);
    int sockSrv = (*(int *) socket);
    while (1) {
        memset(&cli_addr, 0, sizeof(cli_addr));
        int i = recvfrom(sockSrv, buf, 1024, 0, (struct sockaddr *) &cli_addr, (socklen_t *) &cli_len);
        if (i >= 0) {
            printf("%s:%d -- %s\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), buf);
        } else {
            printf("error\n");
            close(sockSrv);
            exit(-1);
        }
    }
}

void udp_client(char *host, int port, char *message) {
    int sockDes = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    struct sockaddr_in addr;
    uint32_t addr_size = sizeof(struct sockaddr_in);
    addr.sin_addr.s_addr = inet_addr(host);
    addr.sin_port = htons(port);
    addr.sin_family = AF_INET;
    ssize_t i = sendto(sockDes, message, 1024, 0, (struct sockaddr *) &addr, addr_size);
    if (i < 0) {
        printf("write error!\n");
    } else {
        printf("success!\n");
    }
    close(sockDes);
}

void udp_client_no_exec() {
    pthread_t udpSocketClientRecv;
    char message[1024];
    char host[1024];
    int serverPort;
    memset(host, 0, 1024);
    memset(&serverPort, 0, 4);
    printf("input address: ");
    scanf("%s", host);
    printf("input port: ");
    scanf("%d", &serverPort);
    int sockDes = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    struct sockaddr_in addr;
    uint32_t addr_size = sizeof(struct sockaddr_in);
    addr.sin_addr.s_addr = inet_addr(host);
    addr.sin_port = htons(serverPort);
    addr.sin_family = AF_INET;
    sendto(sockDes, NULL, 1024, 0, (struct sockaddr *) &addr, addr_size);
    // 开启新线程去接受消息
    pthread_create(&udpSocketClientRecv, NULL, udp_server_recv, (void *) &sockDes);
    printf("\n");
    while (1) {
        memset(message, 0, 1024);
        printf("input message: ");
        scanf("%s", message);
        ssize_t i = sendto(sockDes, message, 1024, 0, (struct sockaddr *) &addr, addr_size);
        if (i < 0) {
            printf("write error!\n");
        } else {
            printf("success!\n");
        }
    }
}